/*-
 * Copyright (c) 2011 Ondrej Fischer <ondrej.fischer@gmail.com>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */
#include "blockingqueue.hpp"
#include "repository.hpp"
#include "job.hpp"
#include "shutdown.hpp"
#include "dispatcher.hpp"

#include "port.hpp"

#define MAKE_DESC    "make -C %s -V PORTNAME -V UNIQUENAME -V PKGNAME -V PKGORIGIN -V PORTEPOCH -V PORTVERSION -V PORTREVISION -V IGNORE -V OPTIONS"
#define MAKE_CONFIG  "make -C %s config-conditional"
#define MAKE_DEPS    "make -C %s -V FETCH_DEPENDS -V EXTRACT_DEPENDS -V PATCH_DEPENDS -V BUILD_DEPENDS -V LIB_DEPENDS -V RUN_DEPENDS"
#define MAKE_FETCH   "make -C %s fetch"
#define MAKE_INSTALL "make -C %s install"

using namespace std;
using namespace express;


int main(int argc, char **argv) {

    int cpu_threads = 3;
    int net_threads = 4;

    /*
     * First we create all the processing queues 
     */
    BlockingQueue<Job::Task> ctr; // Cotrol
    BlockingQueue<Job::Task> man; // Human interaction
    BlockingQueue<Job::Task> cpu; // CPU power
    BlockingQueue<Job::Task> net; // Network bandwidth
    BlockingQueue<Job::Task> evt; // Processing events

    Port::SubmitService submitService;
    Port::SubmitService::Target ctrTgt = submitService.target(ctr);
    Port::SubmitService::Target manTgt = submitService.target(man);
    Port::SubmitService::Target cpuTgt = submitService.target(cpu);
    Port::SubmitService::Target netTgt = submitService.target(net);
    Port::SubmitService::Target evtTgt = submitService.target(evt);

    Shutdown shutdown(manTgt);
    shutdown.add(ctrTgt);
    shutdown.add(cpuTgt);
    shutdown.add(netTgt);
    shutdown.add(evtTgt);

    /*
     * Now all operations are initiated
     */
    Port::System config     (manTgt, MAKE_CONFIG );
    Port::Dependencies deps (cpuTgt, MAKE_DEPS   );
    Port::System fetch      (netTgt, MAKE_FETCH  );
    Port::System install    (cpuTgt, MAKE_INSTALL);


    /*
     * Create the repository of ports, that will create ports using descriptor
     * with initiated operations.
     */
    Repository repository(
        Port::Descriptor(config, deps, fetch, install, shutdown)
    );


    /*
     *   Now we are ready to start the dispatching threads and associate them
     * with appropriate queues.
     */
    Dispatcher(ctr).start();
    Dispatcher(man).start();
    for(int i = 0; i < cpu_threads; i++) Dispatcher(cpu).start();
    for(int i = 0; i < net_threads; i++) Dispatcher(net).start();

    /*
     * Finally we start to process the ports passed as arguments
     */ 
    for(int i = 1; i < argc; i++) repository.getJob(id).initialTask().submit();

    

}

